<?php
declare(strict_types=1);
namespace Service\DeclareService;
use Service\BaseService;
use Service\Code\Normal;
use App\Model\BbcModel\Order;
use App\Model\BbcModel\OrderGoods;
use App\Amqp\Producer\WayBillDeclareMessageProducer;
use Hyperf\Amqp\Producer;
use App\Model\BbcModel\OrderReportLog;
use App\Model\BbcModel\OrderReportStatus;
use Service\ChannelService\StoreConfigService;
use App\Model\BbcModel\Goods;

/**
 * 运单申报服务
 * @author chenshubo
 */
class WayBillDeclareService extends BaseService
{
    public $clear_status = [
        0 => '申报中',
        1 => '清关成功',
        2 => '清关失败',
    ];
    
    public $express_status = [
        0 => '申报中',
        1 => '申报成功',
        2 => '申报失败',
    ];
    
    /**
     * 发布消息队列
     * @param array $msg
     */
    public function publishMsg( array $msg  = [] )
    {
        try {
            $handlerMessage = new WayBillDeclareMessageProducer($msg);
            $producer = container()->get(Producer::class);
            $result = $producer->produce($handlerMessage,true);
            if( $result ) {
                return Normal::returnCode(Normal::SUC,"发布成功");
            }
            return Normal::returnCode(Normal::FAIL,"操作失败，请稍微再试[100000]");
        } catch ( \Throwable $e ) {
            return Normal::returnCode(Normal::FAIL,"操作失败，请稍微再试[{$e->getMessage()},{$e->getLine()},{$e->getFile()}]");
        }
    }
    
    /**
     * 运单申报处理
     * @return mixed
     */
    public function wayBillDeclare( array $param = [] )
    {
        if( empty($param['order_id']) ) {
            return Normal::returnCode(Normal::FAIL,"参数order_id缺失");
        }
        
        $order_id           = $param['order_id'];
        $order_sn           = $param['order_sn'];
        $order_report_id    = $param['order_report_id'];
        $time               = $param['time'] ?? time();
        $logisticreport     = $this->pushLogisticDeclare($param['order_id']);
        if( $logisticreport['code'] == Normal::SUC ) 
        {
            $waybillNo  = $logisticreport['data']['waybillNo'];
            if(!empty($waybillNo)){
                Order::instance()->edit(['id'=>$order_id], ['express_num'=>$waybillNo]);
            }
            $order_report_status_editdata = [
                'express_status'        => 1,
                'express_time'          => $time,
                'express_code'          => $logisticreport['data']['logisticCustomCode'],
                'express_name'          => $logisticreport['data']['logisticCustomName'],
                'express_report_data'   => $logisticreport['data']['originData'],
                'express_type'          => $logisticreport['data']['logisticType']
            ];
            foreach ($order_report_status_editdata as $key => $value) {
                if(empty($value)){
                    unset($order_report_status_editdata[$key]);
                }
            }
            $logisticdata = [
                'order_id'  => $order_id,
                'sn'        => $order_sn,
                'cd'        => $time,
                'content'   => '运单申报成功'
            ];
        }
        else 
        {
            if(isset($logisticreport['data']['waybillNo'])&&$logisticreport['data']['waybillNo']!=''){
                Order::instance()->edit(['id'=>$order_id], ['express_num'=>$logisticreport['data']['waybillNo']]);
            }
            $order_report_status_editdata = ['express_status'=>2,'express_time'=>$time];
            if(isset($logisticreport['data']['originData'])&& $logisticreport['data']['originData']!=''){
                $order_report_status_editdata['express_report_data']=$logisticreport['data']['originData'];
            }
            $logisticdata=[
                'order_id'  => $order_id,
                'sn'        => $order_sn,
                'cd'        => $time,
                'content'   => '运单申报失败:'.$logisticreport['msg']
            ];
        }
        
        OrderReportLog::instance()->add($logisticdata);
        OrderReportStatus::instance()->edit(['id'=>$order_report_id], $order_report_status_editdata);
        return $logisticreport;
    }
    
    /**
     * 运单申报统一入口
     * @param int $order_id
     * @return array
     * @author huj
     */
    public function pushLogisticDeclare(int $order_id,$express_type=null)
    {
        $fields = [
            'id',
            'sn', 
            'price_express', 
            'buyer_mobile',
            'buyer_name', 
            'mn_sid', 
            'receive_info',
            'express_num',
            'buyer_idcard'
        ];
        $order = Order::instance()->info([
            'id'            => $order_id,
            'pay_status'    => 1,
            'df'            => 0,
            '_fields_'      => $fields
        ]);
        if ( empty($order) ) {
            return Normal::returnCode(Normal::FAIL, "订单不存在");
        }
        
        $receiveInfo = @json_decode($order['receive_info'], true);
        if (empty($receiveInfo)) {
            return Normal::returnCode(Normal::FAIL, "订单收货信息不存在");
        }
        
        $receiveInfo = [
            'ReceiverPhone'    => $receiveInfo['mobile'],
            'ReceiverAddress'  => $receiveInfo['address'],
            'ReceiverCountry'  => $receiveInfo['area']['name'],
            'ReceiverCity'     => $receiveInfo['city']['name'],
            'ReceiverProvince' => $receiveInfo['province']['name'],
            'ReceiverName'     => $receiveInfo['true_name'],
        ];
        
        $orderGoods = OrderGoods::instance()->lists(['order_id'=>$order_id]);
        if ( empty($orderGoods) ) {
            return Normal::returnCode(Normal::FAIL, "订单商品不存在");
        }
        
        $goodsIds= array_column($orderGoods, 'goods_id');
        
        $goods= Goods::instance()->lists([['id','in',$goodsIds]]);
        if ( empty($goods) ) {
            return Normal::returnCode(Normal::FAIL, "订单商品不存在2");
        }
        //获取申报运单公司配置
        $mn_sid = $order['mn_sid'];
        $declareWay = StoreConfigService::instance()->getConfig('express_report',$mn_sid);
        if (empty($declareWay) || empty($declareWay['type'])) {
            return Normal::returnCode(Normal::FAIL, "运单申报方式未配置(标识code【express_report】)");
        }
        
        //快递公司接口配置
        $express_report_code = $declareWay['type'];
        if($express_type){
            $express_report_code=$express_type;
        }
        $expressConfig = StoreConfigService::instance()->getConfig($express_report_code,$mn_sid);
        if ( empty($expressConfig) ) {
            return Normal::returnCode(Normal::FAIL, "当前运单公司{$express_report_code}，未配置信息，请联系管理员检查！");
        }
        
        //获取发件人信息配置
        $senderInfo = StoreConfigService::instance()->getConfig('sender_info',$mn_sid);
        if (empty($senderInfo)) {
            return Normal::returnCode(Normal::FAIL, "发货地址信息未配置(标识code【sender_info】)");
        }
        
        $company = StoreConfigService::instance()->getConfig('e_company',$mn_sid);
        if (empty($company)) {
            return Normal::returnCode(Normal::FAIL, "电商平台信息未配置(标识code【e_company】)");
        }
        
        $className  = "Service\\DeclareService\\WayBillCompany\\{$express_report_code}ExpressCompany";
        $callMethod = 'uploadDeclareOrder';
        if (!class_exists($className)) {
            return Normal::returnCode(Normal::FAIL, "服务类【{$className}】不存在");
        }
        if (!method_exists($className, $callMethod)) {
            return Normal::returnCode(Normal::FAIL, "服务类【{$className}】方法【{$callMethod}】不存在");
        }
        
        $result = $className::instance()->$callMethod($expressConfig,[
            'order'         => $order,
            'orderGoods'    => $orderGoods,
            'receiveInfo'   => $receiveInfo,
            'senderInfo'    => $senderInfo,
            'goods'         => array_column($goods, null,'id'),
            'e_company'     => $company
        ]);
        
        $result['data']['order'] = $order;
        $result['data']['logisticCustomCode'] = $expressConfig['logisticCustomCode'] ?? '';
        $result['data']['logisticCustomName'] = $expressConfig['logisticCustomName'] ?? '';
        $result['data']['logisticType'] = $express_report_code;
        return $result;
    }
}
